/*
 * Public Credit Information Sharing Platform(PCISP).
 * Copyright (c) 2019-2020 jsxzkingdee and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * Please visit https://www.zhengxinsoft.com if you need additional information or have any questions.
 */

package com.platform.comm.util.spel;

import com.google.common.base.Strings;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.stream.Stream;

/**
 * Description: Spring SPEL Template
 *
 * @author libinal created on 2020/3/17.
 */

public final class SpelUtil{
    private static ExpressionParser parser = new SpelExpressionParser();

    public static String renderMapTpl(Map<String, Object> root, String exp, Map<String, Object> variables) {
        if (Strings.isNullOrEmpty(exp)) {
            throw new NullPointerException("template expression is not null or empty.");
        }
        StandardEvaluationContext context = new StandardEvaluationContext(root);
        SpelParserConfiguration config = new SpelParserConfiguration(true, true);
        ExpressionParser parser = new SpelExpressionParser(config);
        context.addPropertyAccessor(new MapAccessor());
        if (!CollectionUtils.isEmpty(variables)) {
            context.setVariables(variables);
        }
        addMethods(context);
        Expression expression = parser.parseExpression(exp, new TemplateParserContext());
        return expression.getValue(context, String.class);
    }

    private static void addMethods(StandardEvaluationContext context) {
        Method[] methods = SqlTpl.class.getDeclaredMethods();
        Stream.of(methods).forEach(method -> context.setVariable(method.getName(), method));
    }

    public static String renderMapTpl(Map<String, Object> root, String exp) {
        return  renderMapTpl(root, exp, null);
    }

    public static Expression parseSpel(String spel){
        return parser.parseExpression(spel);
    }

    public static Object getValue(String exp , Map<String, Object> variables){
        ExpressionParser parser = new SpelExpressionParser();
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setVariables(variables);
        return   parser.parseExpression(exp).getValue(context,Object.class);
    }

}
